package com.google.code.sysarch.v4.vrml_loader;

import java.util.ArrayList;
import java.util.HashMap;

import org.lwjgl.opengl.GL11;

import com.google.code.sysarch.v4.graphical.LWJGLGameWindow;

public class VRML_Model {

	private ArrayList<VRML_Shape> shapes = new ArrayList<VRML_Shape>();
	private HashMap<String, float[][]> morph = new HashMap<String, float[][]>();	
	private float[] morphKeys;	
	private float scale_x, scale_y, scale_z;
	private float x,y,z;
	private float rot_x, rot_y, rot_z;
	private int displaylist;
	
	
	public VRML_Model() {
		scale_x = 1f;
		scale_y = 1f;
		scale_z = 1f;
		x = 0f;
		y = 0f;
		z = 0f;
	}
	
	public void translate(float x, float y, float z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}	
	
	public void rotate(float rot_x, float rot_y, float rot_z) {
		this.rot_x = rot_x;
		this.rot_y = rot_y;
		this.rot_z = rot_z;
	}
	
	public void scale(float scale) {
		scale(scale, scale, scale);
	}
	
	public void scale(float x, float y, float z) {
		this.scale_x = x;
		this.scale_y = y;
		this.scale_z = z;
	}
	
	public void setTransparency(float a) {
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i).setTransparency(a);
		}		
	}
	
	public void textureFix(boolean on) {
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i).textureFix(on);
		}		
	}
	
	public float[] getMorphKeys() {
		return this.morphKeys;
	}
	
	public void setMorphKeys(float[] keys) {
		this.morphKeys = keys;
	}
	
	public void addMorph(float[][] list) {
		int i = 0;
		while (this.morph.containsKey("morph"+i)) i++;
		this.morph.put("morph"+i, list);
	}	
	
	public void addShape(VRML_Shape shape) {
		shapes.add(shape);
	}
	
	public void optimize() {
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i).optimize();
		}
	}
	
	public void build() {
		displaylist = GL11.glGenLists(1);
		GL11.glNewList(displaylist, GL11.GL_COMPILE);
		// List begin
		GL11.glColorMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT_AND_DIFFUSE);
		float[] spec = { 0.7f, 0.7f, 0.7f, 1.0f };
		GL11.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_SPECULAR, LWJGLGameWindow.toFloatBuffer(spec));
		GL11.glMaterialf(GL11.GL_FRONT_AND_BACK, GL11.GL_SHININESS, 115);
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i).render();
		}		
		// List end
		GL11.glEndList();
	}
	
	public void render() {
		GL11.glPushMatrix();				
			GL11.glTranslatef(x, y, z);		
			GL11.glRotatef(rot_x, 1, 0, 0);
			GL11.glRotatef(rot_y, 0, 1, 0);
			GL11.glRotatef(rot_z, 0, 0, 1);
			GL11.glScalef(scale_x, scale_y, scale_z);
			GL11.glCallList(displaylist);	
		GL11.glPopMatrix();
	}
	
	public void morph(int from, int to, double adv) {
		GL11.glPushMatrix();		
		GL11.glTranslatef(x, y, z);		
		GL11.glRotatef(rot_x, 1, 0, 0);
		GL11.glRotatef(rot_y, 0, 1, 0);
		GL11.glRotatef(rot_z, 0, 0, 1);
		GL11.glScalef(scale_x, scale_y, scale_z);	
		GL11.glColorMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT_AND_DIFFUSE);
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i).render(this.morph.get("morph"+from), this.morph.get("morph"+to), adv);
		}		
		GL11.glPopMatrix();		
	}
	
	public void cleanup() {
		shapes.clear();
		Runtime.getRuntime().gc();
	}
	
	public void _debug() {
		for (int i=0; i<shapes.size(); i++) {
			shapes.get(i)._debug();
		}
	}
	
}
